package com.datang.litejvm.cmd;

import com.datang.litejvm.constant.ConstantInfo;
import com.datang.litejvm.constant.ConstantPool;
import com.datang.litejvm.constant.ConstantStringInfo;
import com.datang.litejvm.constant.ConstantUTF8Info;
import com.datang.litejvm.engin.ExecutionResult;
import com.datang.litejvm.engin.Heap;
import com.datang.litejvm.engin.JavaObject;
import com.datang.litejvm.engin.StackFrame;

public class LdcCmd extends OneOperandCmd {
    public LdcCmd(ConstantPool pool, String opCode) {
        super(pool, opCode);
    }

    @Override
    public String toString() {
        return super.toString();
    }

    /**
     * @author: 顶风少年
     * @Description: 从运行时常量池中提取数据推入操作数栈
     * index 是一个无符号 byte 型数据，它作为当前类（§2.6）的运行时常量池
     * 的索引使用。index 指向的运行时常量池项必须是一个 int 或者 float 类型
     * 的运行时常量，或者是一个类的符号引用（§5.4.3.1）或者字符串字面量
     * （§5.1）。
     * 如果运行时常量池项必须是一个 int 或者 float 类型的运行时常量，那数值
     * 这个常量所对应的数值 value 将被压入到操作数栈之中。
     * 另外，如果运行时常量池项必须是一个代表字符串字面量（§5.1）的 String
     * 类的引用，那这个实例的引用所对应的 reference 类型数据 value 将被压入
     * 到操作数栈之中。
     * 另外，如果运行时常量池项必须是一个类的符号引用（§4.4.1），这个符号
     * 引用是已被解析（§5.4.3.1）过的，那这个类的 Class 对象所对应的
     * reference 类型数据 value 将被压入到操作数栈之中。
     * @date: 21:37 2022/6/16
     **/
    @Override
    public void execute(StackFrame frame, ExecutionResult result) {
        ConstantInfo constantInfo = getConstantInfo(getOperand());
        if (constantInfo instanceof ConstantStringInfo) {
            ConstantStringInfo constantStringInfo = (ConstantStringInfo) constantInfo;
            int constantStringInfoIndex = constantStringInfo.getIndex();
            ConstantUTF8Info constantUTF8Info = (ConstantUTF8Info) getConstantInfo(constantStringInfoIndex);
            String bytes = constantUTF8Info.getBytes();
            JavaObject javaObject = Heap.getInstance().newString(bytes);
            frame.getOperandStack().push(javaObject);
        } else {
            throw new RuntimeException("Only support StringInfo constant");
        }
    }
}
